package com.tarena.csmall.seckill.service;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.restful.JsonPage;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.pojo.product.vo.SpuStandardVO;
import cn.tedu.mall.pojo.seckill.vo.SeckillSpuVO;
import com.alibaba.fastjson.JSON;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

@Service
public class SeckillSpuService {
    public static final String SECKILL_SPU_LIST="seckill:spu:list";
    @Autowired
    private StringRedisTemplate redisTemplate;
    public JsonPage<SeckillSpuVO> listSpuSeckill() {
        //读取数据了,用户高读查询秒杀商品的时候,不能直接读取数据库
        //读取redis 读取是一个list对象 使用list结构存储redis缓存
        //每一个list元素就是seckillSpuVO的json字符串
        //操作list
        ListOperations<String, String> opsForList = redisTemplate.opsForList();
        //获取缓存的逻辑
        //1. 判断存在
        Boolean exists = redisTemplate.hasKey(SECKILL_SPU_LIST);
        if (!exists){
            //2. 不存在抛一个异常,说明预热没有做到位
            throw new CoolSharkServiceException(ResponseCode.BAD_REQUEST,"预热没有做到位");
        }
        //3. 存在 解析成list 封装到JsonPage里返回
        List<String> spuJsons = opsForList.range(SECKILL_SPU_LIST, 0, -1);
        //4. 解析成list
        List<SeckillSpuVO> spus= new ArrayList<>();
        for (String json : spuJsons){
            //每次都拿到一个spuSeckillVO对象的json
            SeckillSpuVO spuVO = JSON.toJavaObject(JSON.parseObject(json), SeckillSpuVO.class);
            spus.add(spuVO);
        }
        //5. 封装到JsonPage里返回
        return JsonPage.defaultPage(spus);
    }

    public static final String SPU_SECKILL_PREFIX="seckill:spu:";
    public SeckillSpuVO getSeckillSpu(Long spuId) {
        String spuKey=SPU_SECKILL_PREFIX+spuId;
        //1.读取redis 准备当前数据的业务key值
        ValueOperations<String, String> opsForValue =redisTemplate.opsForValue();
        //exists spuKey
        Boolean hasKey = redisTemplate.hasKey(spuKey);
        //2.如果是空，说明预热没有完成
        if (!hasKey){
            throw new CoolSharkServiceException(ResponseCode.BAD_REQUEST,"预热没有做到位");
        }
        //3.如果不是空，计算当前商品开始秒杀时间和结束秒杀时间和当前系统时间对比结果
        String spuJson = opsForValue.get(spuKey);
        //转化成java对象 SeckillSpuVO
        SeckillSpuVO spuVO = JSON.toJavaObject(JSON.parseObject(spuJson), SeckillSpuVO.class);
        //LocalDateTime的api计算 什么是合法时间 startTime<now<endTime 其他都是非法时间
        //拿到系统时间
        LocalDateTime now=LocalDateTime.now();
        //判断系统时间，是否在start之后
        Duration afterStart= Duration.between(now,spuVO.getStartTime()); //afterStart正确的值是negtive
        //判断系统时间，是否在end之前
        Duration beforeEnd= Duration.between(spuVO.getEndTime(),now); //beforeEnd正确的值是negtive
        //4.只要结果没问题，将缓存返回
        //5.如果有问题，将缓存对象保存随机数字地址清空 url
        if(!afterStart.isNegative()&&!beforeEnd.isNegative()){
            //url不能返回给前端，url保证的就是时间合法才返回，时间合法前端才能下单
            spuVO.setUrl(null);
        }
        return spuVO;
    }
}
